package com.yzcrm.erp.psi.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.aop.Aop;
import com.jfinal.aop.Inject;
import com.jfinal.core.Controller;
import com.jfinal.core.paragetter.Para;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.yzcrm.common.annotation.NotNullValidate;
import com.yzcrm.common.annotation.Permissions;
import com.yzcrm.common.config.paragetter.BasePageRequest;
import com.yzcrm.erp.admin.entity.AdminFieldSort;
import com.yzcrm.erp.admin.service.AdminFieldService;
import com.yzcrm.erp.admin.service.AdminSceneService;
import com.yzcrm.erp.crm.common.CrmEnum;
import com.yzcrm.erp.crm.common.CrmExcelUtil;
import com.yzcrm.erp.psi.service.PsiEnterLeaveStockService;
import com.yzcrm.swagger.annotation.ActionApi;
import com.yzcrm.swagger.annotation.Api;
import com.yzcrm.swagger.annotation.Param;
import com.yzcrm.swagger.annotation.Params;
import com.yzcrm.utils.BaseUtil;
import com.yzcrm.utils.R;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author jiang.xue
 * 出入库
 */
@Api(remark = "进销存：出入库")
public class PsiEnterLeaveStockController extends Controller{

    @Inject
    private PsiEnterLeaveStockService psiEnterLeaveStockService;

    @Inject AdminFieldService adminFieldService;

    private static Pattern humpPattern = Pattern.compile("[A-Z]");

    /**
     * @author jiang.xue
     * 查看列表页
     */
    @Permissions({"psi:salesEnter:index", "psi:retrunEnter:index", "psi:repairEnter:index", "psi:testEnter:index", "psi:inventoryProfitEnter:index",
            "psi:otherEnter:index", "psi:purchaseEnter:index", "psi:salesLeave:index", "psi:borrowLeave:index", "psi:repairLeave:index",
            "psi:testLeave:index", "psi:inventoryLossLeave:index", "psi:otherLeave:index"})
    @ActionApi(summary = "检索出入库列表数据", remark="检索出入库列表数据")
    @Params({
            @Param(name="sceneId", remark="场景Id", dataType="int", defaultValue="", required=false),
            @Param(name="type", remark="权限标识 label", dataType="int", defaultValue="", required=true)
    })
    public void queryPageList(BasePageRequest basePageRequest) {

        JSONObject jsonObject = basePageRequest.getJsonObject();
        basePageRequest.setJsonObject(jsonObject);
        renderJson(psiEnterLeaveStockService.filterConditionAndGetPageList(basePageRequest));
    }

    /**
     * @author jiang.xue
     * 添加或者修改出入库
     */
    @ActionApi(summary = "添加或者修改出入库", remark="添加或者修改出入库")
    @Params({
            @Param(name="address", remark="地址，（辽宁省,大连市,高新园区）", dataType="String", defaultValue="", required=false),
            @Param(name="address_detail", remark="地址详细", dataType="String", defaultValue="", required=false),
            @Param(name="location", remark="定位", dataType="String", defaultValue="", required=false)
    })
    @Permissions({"psi:salesEnter:save", "psi:retrunEnter:save", "psi:repairEnter:save", "psi:testEnter:save", "psi:inventoryProfitEnter:save",
            "psi:otherEnter:save", "psi:purchaseEnter:save", "psi:salesLeave:save", "psi:borrowLeave:save", "psi:repairLeave:save",
            "psi:testLeave:save", "psi:inventoryLossLeave:save", "psi:otherLeave:save",
            "psi:salesEnter:update", "psi:retrunEnter:update", "psi:repairEnter:update", "psi:testEnter:update", "psi:inventoryProfitEnter:update",
            "psi:otherEnter:update", "psi:purchaseEnter:update", "psi:salesLeave:update", "psi:borrowLeave:update", "psi:repairLeave:update",
            "psi:testLeave:update", "psi:inventoryLossLeave:update", "psi:otherLeave:update"})
    public void saveOrUpdate(){

        JSONObject jsonObject = JSON.parseObject(getRawData());
        renderJson(psiEnterLeaveStockService.addOrUpdate(jsonObject));
    }

    /**
     * @author jiang.xue
     * 根据id删除出入库
     */
    @ActionApi(summary = "根据id删除出入库", remark="根据id删除出入库")
    @Params({
            @Param(name="elsIds", remark="出入库ID 多个ID,逗号分割", dataType="String", defaultValue="", required=true)
    })
    @Permissions({"psi:salesEnter:delete", "psi:retrunEnter:delete", "psi:repairEnter:delete", "psi:testEnter:delete", "psi:inventoryProfitEnter:delete",
            "psi:otherEnter:delete", "psi:purchaseEnter:delete", "psi:salesLeave:delete", "psi:borrowLeave:delete", "psi:repairLeave:delete",
            "psi:testLeave:delete", "psi:inventoryLossLeave:delete", "psi:otherLeave:delete"})
    @NotNullValidate(value = "elsIds", message = "出入库id不能为空")
    public void deleteByIds(@Para("elsIds") String elsIds) {
        renderJson(psiEnterLeaveStockService.deleteByIds(elsIds));
    }

    /**
     * @author jiang.xue
     * 根据出入库id查询
     */
    @ActionApi(summary = "根据出入库id查询", remark="根据出入库id查询")
    @Params({
            @Param(name="elsId", remark="出入库ID", dataType="String", defaultValue="", required=true)
    })
    @Permissions({"psi:salesEnter:read", "psi:retrunEnter:read", "psi:repairEnter:read", "psi:testEnter:read", "psi:inventoryProfitEnter:read",
            "psi:otherEnter:read", "psi:purchaseEnter:read", "psi:salesLeave:read", "psi:borrowLeave:read", "psi:repairLeave:read",
            "psi:testLeave:read", "psi:inventoryLossLeave:read", "psi:otherLeave:read"})
    @NotNullValidate(value = "elsId", message = "出入库id不能为空")
    public void queryById(@Para("elsId") Integer elsId) {
        renderJson(R.ok().put("data", psiEnterLeaveStockService.queryById(elsId)));
    }

    /**
     * @author jiang.xue
     * 查询出入库明细列表
     */
    @ActionApi(summary = "查询出入库明细列表", remark="查询出入库明细列表，编辑出入库时使用")
    @Params({
            @Param(name="elsId", remark="出入库Id", dataType="Integer", defaultValue="", required=true)
    })
    public void queryEnterLeaveStockDetailByElsId(@Para("elsId") Integer elsId) {
        renderJson(R.ok().put("data", psiEnterLeaveStockService.listEnterLeaveStockDetailByElsId(elsId)));
    }

    /**
     * 全部导出
     */
    public void allExportExcel(BasePageRequest basePageRequest){
        JSONObject jsonObject = basePageRequest.getJsonObject();
        Integer type = Integer.parseInt(jsonObject.getString("type"));
        jsonObject.fluentPut("excel", "yes");
        R data = psiEnterLeaveStockService.getEnterLeaveStockPageList(basePageRequest);
        List<Record> r = JSON.parseObject(data.get("data").toString()).getJSONArray("list").toJavaList(Record.class);
        export(r,type);
        renderNull();
    }
    /**
     * 批量导出
     */
    public void batchExportExcel(BasePageRequest basePageRequest){
        JSONObject jsonObject=basePageRequest.getJsonObject();
        Integer type = Integer.parseInt(jsonObject.getString("type"));
        String ids=jsonObject.getString("ids");
        JSONObject data =new JSONObject();
        data.fluentPut("customerExport",new JSONObject().fluentPut("name","els_id").fluentPut("condition","in").fluentPut("value", ids));
        jsonObject.fluentPut("data",data).fluentPut("search","").fluentPut("excel", "yes");
        basePageRequest.setJsonObject(jsonObject);
        R data2 = psiEnterLeaveStockService.getEnterLeaveStockPageList(basePageRequest);
        List<Record> r = JSON.parseObject(data2.get("data").toString()).getJSONArray("list").toJavaList(Record.class);
        export(r,type);
        renderNull();
    }

    private void export(List<Record> recordList,Integer type){
        ExcelWriter writer = ExcelUtil.getWriter();
        try {
            Long userId = BaseUtil.getUser().getUserId();
            List<Record> headList = Db.findByCache("field", "listHead:" + type + userId, Db.getSql("admin.field.queryListHead"), type, userId);
            headList.forEach(head -> writer.addHeaderAlias(StrUtil.toUnderlineCase(head.getStr("fieldName")),head.getStr("name")));
            writer.merge(headList.size()-1, "信息");
            HttpServletResponse response = getResponse();
            List<Map<String, Object>> list = new ArrayList<>();
            if (recordList.size() == 0){
                Record record = new Record();
                headList.forEach(head -> record.set(StrUtil.toUnderlineCase(head.getStr("fieldName")), ""));
                list.add(record.getColumns());
            }
            recordList.forEach(record -> {
                for (int i = 0; i < headList.size(); i++) {
                    String fieldName = humpToLine(headList.get(i).get("fieldName"));
                    if(record.getStr(fieldName) == null){
                        record.set(fieldName,"");
                    }
                }
                record.set("update_time",timeStamp2Date(record.getStr("update_time"),null));
                record.set("create_time",timeStamp2Date(record.getStr("create_time"),null));
                record.set("els_date",timeStamp2Date(record.getStr("els_date"),null));
                list.add(record.getColumns());
            });
            writer.setOnlyAlias(true);
            writer.write(list, true);
            writer.setRowHeight(0, 20);
            writer.setRowHeight(1, 20);
            for (int i = 0; i < headList.size(); i++) {
                writer.setColumnWidth(i, 20);
            }
            Cell cell = writer.getCell(0, 0);
            CellStyle cellStyle = cell.getCellStyle();
            cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            Font font = writer.createFont();
            font.setBold(true);
            font.setFontHeightInPoints((short) 16);
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            //自定义标题别名
            //response为HttpServletResponse对象
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            response.setHeader("Content-Disposition", "attachment;filename=customer.xls");
            ServletOutputStream out = response.getOutputStream();
            writer.flush(out);
        } catch (Exception e) {
            Log.getLog(getClass()).error("导出客户错误：",e);
        } finally {
            // 关闭writer，释放内存
            writer.close();
        }
    }

    /**驼峰转下划线*/
    public static String humpToLine(String str) {
        Matcher matcher = humpPattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 时间戳转换成日期格式字符串
     */
    public static String timeStamp2Date(String seconds,String format) {
        if(seconds == null || seconds.isEmpty() || seconds.equals("null")){
            return "";
        }
        if(format == null || format.isEmpty()){
            format = "yyyy-MM-dd HH:mm:ss";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(new Date(Long.valueOf(seconds)));
    }

    /**
     * 获取导入模板
     */
    public void downloadExcel(Integer label) {
        List<Record> recordList = adminFieldService.queryAddField(CrmEnum.parse(label));
        recordList.removeIf(record -> "file".equals(record.getStr("formType")) || "checkbox".equals(record.getStr("formType")) || "user".equals(record.getStr("formType")) || "structure".equals(record.getStr("formType")));
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet("导入表");
        sheet.setDefaultRowHeight((short) 400);
        CellStyle textStyle = wb.createCellStyle();
        DataFormat format = wb.createDataFormat();
        textStyle.setDataFormat(format.getFormat("@"));
        for (int i = 0; i < recordList.size() + 2; i++) {
            sheet.setDefaultColumnStyle(i, textStyle);
            sheet.setColumnWidth(i, 20 * 256);
        }
        HSSFRow titleRow = sheet.createRow(0);
        CellStyle cellStyle = wb.createCellStyle();
        cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font font = wb.createFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 16);
        cellStyle.setFont(font);
        titleRow.createCell(0).setCellValue("导入模板(*)为必填项");
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        titleRow.getCell(0).setCellStyle(cellStyle);
        CellRangeAddress region = new CellRangeAddress(0, 0, 0, recordList.size()-1);
        sheet.addMergedRegion(region);
        try {
            HSSFRow row = sheet.createRow(1);
            for (int i = 0; i < recordList.size(); i++) {
                Record record = recordList.get(i);
                HSSFCell cell = row.createCell(i);
                if (record.getInt("is_null") == 1) {
                    cell.setCellValue(record.getStr("name") + "(*)");
                } else {
                    cell.setCellValue(record.getStr("name"));
                }
                String[] setting = record.get("setting");
                if (setting != null && setting.length != 0) {
                    CellRangeAddressList regions = new CellRangeAddressList(2, Integer.MAX_VALUE, i, i);
                    DVConstraint constraint = DVConstraint.createExplicitListConstraint(setting);
                    HSSFDataValidation dataValidation = new HSSFDataValidation(regions, constraint);
                    sheet.addValidationData(dataValidation);
                }
            }
            HttpServletResponse response = getResponse();
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            response.setHeader("Content-Disposition", "attachment;filename=customer_import.xls");
            wb.write(response.getOutputStream());

        } catch (Exception e) {
            Log.getLog(getClass()).error("error", e);
        } finally {
            try {
                wb.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }

        }
        renderNull();
    }

//    /**
//     * @author jiang.xue
//     * 出入库编号查询
//     */
//    @ActionApi(summary = "出入库编号查询", remark="出入库编号查询")
//    @Params({@Param(name="elsNum", remark="出入库编号", dataType="String", defaultValue="", required=false),
//            @Param(name="label", remark="模块编号", dataType="Integer", defaultValue="", required=true)
//    })
//    public void queryElsNum(@Para("elsNum") String elsNum, @Para("label") Integer label) {
//        renderJson(psiEnterLeaveStockService.queryElsNum(elsNum, label));
//    }


    /**
     * @author jiang.xue
     * 出入库导出
     */
    @ActionApi(summary = "出入库导出", remark="出入库导出")
    @Params({
            @Param(name="startDate", remark="开始日期", dataType="String", defaultValue="", required=false),
            @Param(name="endDate", remark="结束日期", dataType="String", defaultValue="", required=false),
            @Param(name="label", remark="模块label ", dataType="Int", defaultValue="", required=true),
            @Param(name="page", remark="页码", dataType="Int", defaultValue="", required=true),
            @Param(name="limit", remark="每页数量", dataType="Int", defaultValue="", required=true)
    })
//    @Permissions({"psi:querystorehouse:querystorehouse", "psi:querystorehouse:querystorehouse_salesman","psi:querystorehouse:querystorehouse_director","psi:querystorehouse:querystorehouse_purchaser"})
    public void queryEnterLeaveStock(@Para("startDate") String startDate,
                                @Para("endDate") String endDate,
                                @Para("label") Integer label,
                                @Para("page") int page,
                                @Para("limit") int limit) {
//        renderJson(storehouseService.queryStorehouse(productId,productName,productStatus,productNameEn,productNum,
//                productSpecName,storehouseId,storehouseCode,storehouseName,productBatchId,productUpcCode, elsNum, page,limit));
    }

    /**
     * 出入库导出表头信息
     */
    @ActionApi(summary = "出入库导出 表头", remark="出入库导出 表头")
    public void queryEnterLeaveStockListHead() {

//        renderJson(R.ok().put("data", storehouseService.queryStorehouseListHead()));
    }


}
